#include "modelitem.h"

ModelItem::ModelItem(QObject *parent) :
    QObject(parent),
    d(new Data())
{
    initialize();
}

ModelItem::ModelItem(const ModelItem &other) :
    QObject(other.parent()),
    d(other.d)
{
    initialize();
}

QString ModelItem::name() const
{
    return d->name;
}

void ModelItem::setName(const QString &name)
{
    if (name == d->name)
    {
        return;
    }

    d->name = name;

    emit sigChanged();

    onRefresh();
}

bool ModelItem::childrenOrdered() const
{
    return d->orderChildren;
}

void ModelItem::setChildrenOrdered(bool ordered)
{
    d->orderChildren = ordered;
}

int ModelItem::type() const
{
    return qMetaTypeId<ModelItem*>();
}

QVariant ModelItem::sortData() const
{
    return name();
}


void ModelItem::setParent(QObject *object)
{
    disconnect(parent(), 0, this, 0);
    disconnect(this, 0, parent(), 0);

    QObject::setParent(object);

    onRefresh();
    initialize();
}

ModelItem *ModelItem::parentItem() const
{
    return qobject_cast<ModelItem*>(parent());
}

const ModelItem *ModelItem::rootItem() const
{
    ModelItem* item = parentItem();
    if (!item)
    {
        return this;
    }

    return item->rootItem();
}

QList<ModelItem *> ModelItem::childItems() const
{
    QList<ModelItem *> childList = findChildren<ModelItem*>(QString(), Qt::FindDirectChildrenOnly);
    if (!childrenOrdered())
    {
        return childList;
    }

    QMap<QString, ModelItem*> childMap;
    foreach (ModelItem* childItem, childList)
    {
        childMap.insert(childItem->name(), childItem);
    }

    return childMap.values();
}

void ModelItem::onRefresh()
{
    if (this == rootItem())
    {
        d->name.clear();
        emit sigRefresh();
    }

    ModelItem* item = parentItem();
    if (!item)
    {
        return;
    }

    if (item == rootItem())
    {
        setObjectName(d->name);
    }
    else
    {
        setObjectName(QString("%1.%2").arg(item->objectName()).arg(d->name));
    }

    emit sigRefresh();
}

void ModelItem::initialize()
{
    disconnect(this, 0, 0, 0);

    ModelItem* item = parentItem();
    if (!item)
    {
        return;
    }

    connect(this, SIGNAL(sigChanged()), item, SIGNAL(sigChanged()), Qt::UniqueConnection);
    connect(item, SIGNAL(sigRefresh()), this, SLOT(onRefresh()), Qt::UniqueConnection);
}

